package qp.src.app.client;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import qp.src.app.client.widget.PageMode;
import qp.src.app.shared.DataBeanProxy;
import qp.src.app.shared.DataBeanRequest;
import qp.src.app.shared.DataGridRequestFactory;

import com.google.gwt.cell.client.CheckboxCell;
import com.google.gwt.cell.client.DatePickerCell;
import com.google.gwt.cell.client.EditTextCell;
import com.google.gwt.cell.client.NumberCell;
import com.google.gwt.cell.client.TextCell;
import com.google.gwt.cell.client.TextInputCell;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.i18n.client.DateTimeFormat;
import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.DataGrid;
import com.google.gwt.user.cellview.client.SimplePager;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.SimplePager.TextLocation;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.view.client.DefaultSelectionEventManager;
import com.google.gwt.view.client.ListDataProvider;
import com.google.gwt.view.client.MultiSelectionModel;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SingleSelectionModel;
import com.google.web.bindery.requestfactory.shared.EntityProxyId;

public class DataGridUi {

  private DataGrid<DataBeanProxy> dataGrid;
  private Column<DataBeanProxy, Number> rowNumberColumn;
  private ListDataProvider<DataBeanProxy> dataProviderX;
  private MultiSelectionModel<DataBeanProxy> multiSelection;
  private SingleSelectionModel<DataBeanProxy> singleSelect;
  private ListHandler<DataBeanProxy> handler;
  private Button getAllDataBtn;
  private Button getSelectBtn;
  private Button addByPopup;
  private Button removeBtn;
  private Button editBtn;
  private DataGridPopup popup = new DataGridPopup();
  private AddPopup testPopup = new AddPopup();

  private DataGridRequestFactory factory;

  /**************        CONSTUCTOR        **************/

  public DataGridUi(DataGridRequestFactory factory){
    this.factory = factory;
  }

  /**************        EVENT HANDLER        **************/

  private ClickHandler addDataByPopup = new ClickHandler() {
    public void onClick(ClickEvent event) {
      System.out.println("ADD");
      testPopup.openPopup(PageMode.ADD, new Object[]{factory});
    }
  };

  private ClickHandler editHandler = new ClickHandler() {
    public void onClick(ClickEvent event) {
      popup.openPopup(PageMode.EDIT, getSelectionData());
    }
  };

  private ClickHandler removeHandler = new ClickHandler() {
    public void onClick(ClickEvent event) {
      DataBeanProxy dataBeanProxy = singleSelect.getSelectedObject();
      DataBeanRequest request = factory.dataBeanRequest();
      request.delete(dataBeanProxy).fire();
    }
  };

  /**************        GRID UTIL        **************/

  public void addDataToGrid(DataBeanProxy dataProxy){
    List<DataBeanProxy> data = dataProviderX.getList();
    data.add( dataProxy );

    dataProviderX.setList(data);
    dataProviderX.refresh();
    setSortHandler();
  }

  public void updateDataToGrid(DataBeanProxy proxy){
    DataBeanProxy editData = singleSelect.getSelectedObject();
    List<DataBeanProxy> list= dataProviderX.getList();
    int row = list.lastIndexOf(editData);
    list.remove(editData);
    list.add(row, proxy);
    dataProviderX.setList(list);
    dataProviderX.refresh();
    setSortHandler();
  }

  public void removeDataToGrid(EntityProxyId<DataBeanProxy> id){
    List<DataBeanProxy> data = dataProviderX.getList();
    int displayOffset = offsetOf(id);
    if (displayOffset != -1) {
      data.remove(displayOffset);
    }

    dataProviderX.setList(data);
    dataProviderX.refresh();
  }

  /**************        INITIAL        **************/

  public VerticalPanel [] init() {
    getAllDataBtn = new Button("Get All Data");
    getAllDataBtn.setWidth("200");
    getAllDataBtn.addClickHandler(getAllDataBtnHandler);

    getSelectBtn = new Button("Get Select Data");
    getSelectBtn.setWidth("200");
    getSelectBtn.addClickHandler(selectBtnHandler);
    getSelectBtn.setEnabled(false);

    VerticalPanel vPanel = new VerticalPanel();
    vPanel.add(getAllDataBtn);
    vPanel.add(getSelectBtn);
    vPanel.setSpacing(2);

    // ******************************************************************************
    dataGrid = new DataGrid<DataBeanProxy>();
    dataGrid.setWidth("700");
    dataGrid.setHeight("450");

    // ******************************************************************************
    // SingleSelection && MultiSelection
    // ******************************************************************************
//    multiSelection = new MultiSelectionModel<DataBeanProxy>();
//    dataGrid.setSelectionModel(multiSelection, DefaultSelectionEventManager
//        .<DataBeanProxy> createCheckboxManager());
//    multiSelection.addSelectionChangeHandler(selectionHandler);

    singleSelect = new SingleSelectionModel<DataBeanProxy>();
    dataGrid.setSelectionModel(singleSelect, DefaultSelectionEventManager
      .<DataBeanProxy> createCheckboxManager());
    singleSelect.addSelectionChangeHandler(selectionHandler);

    Column<DataBeanProxy, Boolean> checkColumn = new Column<DataBeanProxy, Boolean>(
        new CheckboxCell(true, false)) {
      public Boolean getValue(DataBeanProxy object) {
        return singleSelect.isSelected(object);
      }
    };

    // ******************************************************************************
    // Grid Column
    // ******************************************************************************
    rowNumberColumn = new Column<DataBeanProxy, Number>(new NumberCell()) {
      public Number getValue(DataBeanProxy object) {
        return object.getId();
      }
    };

    rowNumberColumn.setSortable(true);

    Column<DataBeanProxy, String> col1 = new Column<DataBeanProxy, String>(
        new EditTextCell()) {
      public String getValue(DataBeanProxy object) {
        return object.getName();
      }
    };

    Column<DataBeanProxy, String> col2 = new Column<DataBeanProxy, String>(
        new TextInputCell()) {
      public String getValue(DataBeanProxy object) {
        return object.getLastName();
      }
    };

    Column<DataBeanProxy, String> col3 = new Column<DataBeanProxy, String>(new TextCell()) {
      public String getValue(DataBeanProxy object) {
        return object.getAddress();
      }
    };

    DateTimeFormat dateFormat = DateTimeFormat
        .getFormat(PredefinedFormat.DATE_MEDIUM);

    Column<DataBeanProxy, Date> col4 = new Column<DataBeanProxy, Date>(
        new DatePickerCell(dateFormat)) {
      public Date getValue(DataBeanProxy object) {
        return object.getDateTime();
      }
    };

    dataGrid.setColumnWidth(rowNumberColumn, 100, Unit.PX);
    dataGrid.setColumnWidth(col1, 200, Unit.PX);
    dataGrid.setColumnWidth(col2, 200, Unit.PX);
    dataGrid.setColumnWidth(col3, 200, Unit.PX);
    dataGrid.setColumnWidth(col4, 200, Unit.PX);

    dataGrid.setColumnWidth(checkColumn, "40");

    dataGrid.addColumn(checkColumn);
    dataGrid.addColumn(rowNumberColumn, "ID", "###ID###");
    dataGrid.addColumn(col1, "NAME");
    dataGrid.addColumn(col2, "LASTNAME");
    dataGrid.addColumn(col3, "ADRESS");
    dataGrid.addColumn(col4, "DATE");

    // ******************************************************************************
    SimplePager.Resources pagerResources = GWT
        .create(SimplePager.Resources.class);

    dataProviderX = new ListDataProvider<DataBeanProxy>();
    setSortHandler();

    dataProviderX.addDataDisplay(dataGrid);

    SimplePager pagerX = new SimplePager(TextLocation.CENTER, pagerResources,
        false, 0, true);
    pagerX.setDisplay(dataGrid);
    pagerX.setPageSize(10);

    addByPopup = new Button("AddByPopup");
    removeBtn = new Button("Remove");
    editBtn = new Button("Edit");

    addByPopup.addClickHandler(addDataByPopup);
    removeBtn.addClickHandler(removeHandler);
    editBtn.addClickHandler(editHandler);

    removeBtn.setEnabled(false);
    editBtn.setEnabled(false);

    HorizontalPanel manageBtnPanel = new HorizontalPanel();
    manageBtnPanel.setSpacing(5);
    manageBtnPanel.add(addByPopup);
    manageBtnPanel.add(removeBtn);
    manageBtnPanel.add(editBtn);

    VerticalPanel gridPanel = new VerticalPanel();
    gridPanel.add(manageBtnPanel);
    gridPanel.add(dataGrid);
    gridPanel.add(pagerX);

    VerticalPanel [] listPanel = new VerticalPanel[]{vPanel, gridPanel};
    return listPanel;
  }

  // ******************************************************************************
  // Get Data
  // ******************************************************************************
  private Object[] getSelectionData() {
    DataBeanProxy dataBeanProxy = singleSelect.getSelectedObject();
    Object [] objects = new Object []{
        factory,
        dataBeanProxy
    };
    return objects;
  }

  private List<DataBeanProxy> getMultiSelection() {
    List<DataBeanProxy> data = new ArrayList<DataBeanProxy>(multiSelection
        .getSelectedSet());
    return data;
  }

  private List<DataBeanProxy> getAllData() {
    List<DataBeanProxy> data = new ArrayList<DataBeanProxy>(dataProviderX.getList());
    return data;
  }

  // ******************************************************************************
  // Set Data
  // ******************************************************************************
  public void setData(List<DataBeanProxy> dataBeans){
    dataProviderX.setList( dataBeans );
  }

  private void setSortHandler() {
    handler = new ListHandler<DataBeanProxy>(dataProviderX.getList());
    dataGrid.addColumnSortHandler(handler);

    handler.setComparator(rowNumberColumn, new Comparator<DataBeanProxy>() {
      public int compare(DataBeanProxy bean1, DataBeanProxy bean2) {
        return bean1.getId().compareTo(bean2.getId());
      }
    });
  }

  // ******************************************************************************
  private SelectionChangeEvent.Handler selectionHandler = new SelectionChangeEvent.Handler() {
    public void onSelectionChange(SelectionChangeEvent event) {
      DataBeanProxy selectedProxy = singleSelect.getSelectedObject();
      if( selectedProxy != null ){
        getSelectBtn.setEnabled(true);
        removeBtn.setEnabled(true);
        editBtn.setEnabled(true);
      }
      else{
        getSelectBtn.setEnabled(false);
        removeBtn.setEnabled(false);
        editBtn.setEnabled(false);
      }
    }
  };

  // ******************************************************************************
  // Click Handler
  // ******************************************************************************
  private ClickHandler getAllDataBtnHandler = new ClickHandler() {
    public void onClick(ClickEvent event) {
      List<DataBeanProxy> data = getAllData();

      for (DataBeanProxy bean : data) {
        System.out.print("ID = " + bean.getId() + "\t");
        System.out.print("NAME = " + bean.getName() + "\t");
        System.out.print("LASTNAME = " + bean.getLastName() + "\t");
        System.out.println("ADDRESS = " + bean.getAddress());
        System.out.println("#############################");
      }
    }
  };

  private ClickHandler selectBtnHandler = new ClickHandler() {
    public void onClick(ClickEvent event) {
      List<DataBeanProxy> data = getMultiSelection();

      for (DataBeanProxy bean : data) {
        System.out.print("ID = " + bean.getId() + "\t");
        System.out.print("NAME = " + bean.getName() + "\t");
        System.out.println("LASTNAME = " + bean.getLastName() + "\t");
        System.out.println("#############################");
      }
    }
  };

  // ******************************************************************************

  private int offsetOf(EntityProxyId<DataBeanProxy> dataBeanProxy) {
    List<DataBeanProxy> displayedItems = dataGrid.getVisibleItems();
    for (int offset = 0; offset < displayedItems.size(); offset++) {
      if (dataBeanProxy.equals(displayedItems.get(offset).stableId())) {
        return offset;
      }
    }
    return -1;
  }

  public DataGrid<DataBeanProxy> getDataGrid(){
    return dataGrid;
  }

}
